<template>
  <div
    id="drawflow"
    class="parent-drawflow relative"
    @drop="dropHandler"
    @dragover.prevent
  >
    <slot></slot>
    <div class="absolute z-10 p-4 bottom-0 left-0">
      <button
        v-tooltip.group="'Reset zoom'"
        class="p-2 rounded-lg bg-white mr-2"
        @click="editor.zoom_reset()"
      >
        <v-remixicon name="riFullscreenLine" />
      </button>
      <div class="rounded-lg bg-white inline-block">
        <button
          v-tooltip.group="'Zoom out'"
          class="p-2 rounded-lg relative z-10"
          @click="editor.zoom_out()"
        >
          <v-remixicon name="riSubtractLine" />
        </button>
        <hr class="h-6 border-r inline-block" />
        <button
          v-tooltip.group="'Zoom in'"
          class="p-2 rounded-lg"
          @click="editor.zoom_in()"
        >
          <v-remixicon name="riAddLine" />
        </button>
      </div>
    </div>
  </div>
</template>
<script>
/* eslint-disable camelcase */
import { onMounted, shallowRef, getCurrentInstance } from 'vue';
import emitter from 'tiny-emitter/instance';
import { tasks } from '@/utils/shared';
import { useGroupTooltip } from '@/composable/groupTooltip';
import drawflow from '@/lib/drawflow';

export default {
  props: {
    data: {
      type: [Object, String],
      default: null,
    },
  },
  emits: ['load', 'deleteBlock'],
  setup(props, { emit }) {
    useGroupTooltip();

    const editor = shallowRef(null);

    function dropHandler({ dataTransfer, clientX, clientY }) {
      const block = JSON.parse(dataTransfer.getData('block') || null);
      const isTriggerExists =
        block.id === 'trigger' &&
        editor.value.getNodesFromName('trigger').length !== 0;

      if (!block || isTriggerExists) return;

      const xPosition =
        clientX *
          (editor.value.precanvas.clientWidth /
            (editor.value.precanvas.clientWidth * editor.value.zoom)) -
        editor.value.precanvas.getBoundingClientRect().x *
          (editor.value.precanvas.clientWidth /
            (editor.value.precanvas.clientWidth * editor.value.zoom));
      const yPosition =
        clientY *
          (editor.value.precanvas.clientHeight /
            (editor.value.precanvas.clientHeight * editor.value.zoom)) -
        editor.value.precanvas.getBoundingClientRect().y *
          (editor.value.precanvas.clientHeight /
            (editor.value.precanvas.clientHeight * editor.value.zoom));

      editor.value.addNode(
        block.id,
        block.inputs,
        block.outputs,
        xPosition,
        yPosition,
        block.id,
        block.data,
        block.component,
        'vue'
      );
      emitter.emit('editor:data-changed');
    }
    function isInputAllowed(allowedInputs, input) {
      if (typeof allowedInputs === 'boolean') return allowedInputs;

      return allowedInputs.some((item) => {
        if (item.startsWith('#')) {
          return tasks[input].category === item.substr(1);
        }

        return item === input;
      });
    }

    onMounted(() => {
      /* eslint-disable-next-line */
      const context = getCurrentInstance().appContext.app._context;
      const element = document.querySelector('#drawflow');

      editor.value = drawflow(element, { context, options: { reroute: true } });
      editor.value.start();

      emit('load', editor.value);

      if (props.data) {
        const data =
          typeof props.data === 'string'
            ? JSON.parse(props.data.replace(/BlockNewTab/g, 'BlockBasic'))
            : props.data;

        editor.value.import(data);
      } else {
        editor.value.addNode(
          'trigger',
          0,
          1,
          50,
          300,
          'trigger',
          { type: 'manual' },
          'BlockBasic',
          'vue'
        );
      }

      editor.value.on('nodeRemoved', (id) => {
        emit('deleteBlock', id);
      });
      editor.value.on(
        'connectionCreated',
        ({ output_id, input_id, output_class, input_class }) => {
          const { outputs } = editor.value.getNodeFromId(output_id);
          const { name: inputName } = editor.value.getNodeFromId(input_id);
          const { allowedInputs, maxConnection } = tasks[inputName];
          const isAllowed = isInputAllowed(allowedInputs, inputName);
          const isMaxConnections =
            outputs[output_class]?.connections.length > maxConnection;

          if (!isAllowed || isMaxConnections) {
            editor.value.removeSingleConnection(
              output_id,
              input_id,
              output_class,
              input_class
            );
          }

          emitter.emit('editor:data-changed');
        }
      );
      editor.value.on('connectionRemoved', () => {
        emitter.emit('editor:data-changed');
      });

      setTimeout(() => {
        editor.value.zoom_refresh();
      }, 500);
    });

    return {
      editor,
      dropHandler,
    };
  },
};
</script>
<style>
#drawflow {
  background-image: url('@/assets/images/tile.png');
  background-size: 35px;
}
</style>
